open Printf
open Ext

(* Globals used for command line parameters *)
let modelfile = ref ""
let outfile = ref ""
let threshold = ref 0.0
let onlyprune = ref false
let prethresh = ref false
let maxsize = ref 0.0

let usage = "Usage: acve -m <model> [-o <circuit>] [...]"
let args = Arg.align
 ([("-m", Arg.Set_string modelfile, " Model file (BN or MN)") ;
   ("-o", Arg.Set_string outfile, " Output circuit")] 
(* EXPERIMENTAL AC pruning strategies -- DISABLED FOR NOW.
   ("-t", Arg.Set_float threshold, " Approximation threshold") ;
   ("-pt", Arg.Set prethresh, " Apply threshold in advance") ;
   ("-ms", Arg.Set_float maxsize, " Maximum ADD size") ;
   ("-p", Arg.Set onlyprune, " Simple pruning method") *)
   @ common_arguments)

let main () =
  Arg.parse args ignore usage;
  if !modelfile = "" (* || !outfile = "" *) then
    Arg.usage args usage
  else begin
    common_log_init ();
    let mn =
      match filetype !modelfile with
      | BNFile -> Bn.to_mn (Bn.load_auto !modelfile)
      | MNFile -> Mn.load_auto !modelfile
      | _ -> nlogf "ERROR: Unsupported file type.\n"; exit (-1) in
    let schema = Mn.schema mn in
    let buildac = !outfile <> "" in
    let (acroot, adds) = 
      if !prethresh then
        if !onlyprune then AcveImpl.varelim_prune buildac !threshold mn
                      else AcveImpl.varelim_choose buildac !threshold mn
      else
        if !onlyprune then AcveImpl.varelim_prune_m buildac !maxsize mn
                      else AcveImpl.varelim_choose_m buildac !maxsize mn in
      
    let before = Sys.time() in
    if buildac then begin
      let ostream = open_out !outfile in
      (* HACK: Need to get the maximum id of output nodes, so that we
       * don't output any features with node ids that exceed that. *)
      Circuit.output_root ostream schema acroot;
      let fl = Add.circuit_features adds in
      let size = List.length (Circuit.root_to_list acroot) in
      output_string ostream "\n";
      Circuit.output_feature_list ostream (Circuit.node_output_id size) fl;
      let after = Sys.time() in
      nlogf "Creating circuit: %fs\n" (after -. before) 
    end else begin
      let v = 
        if Circuit.is_times acroot then begin
          dlogf "DEBUG 1\n";
          List.sumf_map Circuit.const_value (Circuit.children acroot);
        end else
          Circuit.const_value acroot in
      nlogf "%f\n" v
    end
  end

let _ = main ()
